package pkg.lbmg.org;

import java.util.Arrays;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import org.xmlpull.v1.XmlPullParser;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.TextView;

public class MainGameMap extends MapActivity implements OnClickListener{
	
    
	// Preference file
    public static final String PREF_FILE = "pf_file";
    private SharedPreferences preferences;

	// General Activity
    private MapView mapView;
    
    // Score and timer
    int matchScore;
    int matchTime;
    
    // Player State Thread Timer
    TimerTask refreshPlayerStateTask;
	final Handler handlerPlayerState = new Handler();
	Timer tPlayerState = new Timer();
    
	// Game Session
    public 	int	gamePhase = Utils.CREATED; 
	
	// Location
	private static final int NEWER_CHECK = 1000 * 2;
	private GeoPoint pointPlayer, pointTest;
    private Location bestLocation;
    private LocationManager locationManager;
    private LocationListener locationListener;
    private Double latDoubleValue = (double) 0, lonDoubleValue = (double) 0;
    public Double myLon = (double) 0, myLat = (double) 0;
	
	// Overlays
	private List<Overlay> mapOverlays;
	private List<Overlay> mapOverlaysPlaces;
	private Drawable posmarker, placesMarker;
	private OverlayItem playerOverlayItem;
	private OverlayManager itemizedoverlay;
	
    // Radar Overlays
    private OverlayItem placesOverlay;
    private PlaceOverlayManager placesOverlayManager;
	
	// UI
    private PowerManager.WakeLock wl; 
    
    // PLACES
    public Place[] allPlaces = new Place[100];
    public int totalPlaces = 0;
    	
	 /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(
        WindowManager.LayoutParams.FLAG_FULLSCREEN,
        WindowManager.LayoutParams.FLAG_FULLSCREEN);
        
        PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);  
        wl = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "DoNotDimScreen"); 
        
        // creates the activity
        setContentView(R.layout.maingamemap);
        
        registerViews();
        setupOnClickListeners();
        
        loadPrefs();
        
        Log.d("MGM", "latDoubleValue" + latDoubleValue);
        Log.d("MGM", "lonDoubleValue" + lonDoubleValue);
        
        setUpContainers();
       
	    mapOverlays = mapView.getOverlays();
	    mapOverlaysPlaces = mapView.getOverlays();   
	    
	    posmarker = this.getResources().getDrawable(R.drawable.dotblue);
	    itemizedoverlay = new OverlayManager(posmarker, this);
	    

	    
	    placesMarker = this.getResources().getDrawable(R.drawable.dotgreen);
	    placesOverlayManager = new PlaceOverlayManager(placesMarker, this);
	    
	    loadPlaces();
	    
	    
	    
	    
	    
	    
	    
	    
//	    THATS HOW A MARKER IS CHANGED!
//	    allPlaces[0].icon.setMarker(posmarker);
	    
	    Double latTest, lonTest;
	    
	    latTest = 55.659946  * 1E6;
        lonTest = 12.591802  * 1E6;
        
        Double latIntTest = 55.659946  * 1E6;
        Double lonIntTest = 12.591802  * 1E6;
  
        pointTest = new GeoPoint(latIntTest.intValue(), lonIntTest.intValue());
        
//        placesOverlay = new OverlayItem(pointTest, "", "");
//        placesOverlayManager.addOverlay(placesOverlay);
//        mapOverlaysPlaces.add(placesOverlayManager);
	    
        
        
        
        
        
        // if you created the game
        // center the map on your first position and update 
        // the center values on the database

        if(latDoubleValue!=0 && lonDoubleValue!=0) {
            // if we already have a clear position
            // set the center position of the game

            Log.d("CENTER LAT", latDoubleValue+"");
            Log.d("CENTER LON", lonDoubleValue+"");
            
            pointPlayer = new GeoPoint(latDoubleValue.intValue(), lonDoubleValue.intValue());
            
            
            
            mapView.setSatellite(true);
            mapView.setStreetView(false);
            mapView.setTraffic(false);
            mapView.getController().setZoom(16);
            mapView.setBuiltInZoomControls(true);
            mapView.displayZoomControls(true);
            mapView.setClickable(true);
            mapView.getController().stopPanning();
            mapView.setHapticFeedbackEnabled(true);
            mapView.getController().setCenter(pointPlayer);
        
            // Add the point to the mapview
            playerOverlayItem = new OverlayItem(pointPlayer, "", "");
            itemizedoverlay.addOverlay(playerOverlayItem);
            mapOverlays.add(itemizedoverlay);

            mapView.postInvalidate();
            
        } else {
            
            // otherwise set the variable for setting it 
            // at the first clear location we have
        
        }
               
    }

	private void loadPrefs() {
        
        preferences = getSharedPreferences(PREF_FILE, MODE_PRIVATE);

    	lonDoubleValue = (double) preferences.getInt("lonDoubleValuePref", 0);
        latDoubleValue = (double) preferences.getInt("latDoubleValuePref", 0);
        
        myLat = (double) preferences.getInt("latDoubleValue", 0);
        myLon = (double) preferences.getInt("lonDoubleValue", 0);
    }
	
	
	public void reloadMyValues() {
        myLat = (double) preferences.getInt("latDoubleValue", 0);
        myLon = (double) preferences.getInt("lonDoubleValue", 0);
	}

	private void setUpContainers() {

	    mapView    = (MapView)  findViewById(R.id.mapview);
		
	}

	private void locateMe() {

	    // Acquire a reference to the system Location Manager
	    locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

	    Log.d("LOCATEME", " CALLED *************************************************");
	    
	    // Define a listener that responds to location updates
	    locationListener = new LocationListener() {
	        
	        public void onLocationChanged(Location location) {

	            if( isBetterLocation(location, bestLocation) ) {

	                // if the new location is the most accurate
	                // set it as the current best location
	                bestLocation = location;

	                latDoubleValue = location.getLatitude();
	                lonDoubleValue = location.getLongitude();

	                if (latDoubleValue != 0 && lonDoubleValue != 0) {

	                    // Called when a new location is found by the GPS location
	                    // provider update the lat and lon local values
	                    latDoubleValue = location.getLatitude() * 1E6;
	                    lonDoubleValue = location.getLongitude() * 1E6;

	                    pointPlayer = new GeoPoint(latDoubleValue.intValue(), lonDoubleValue.intValue());

	                    if(mapOverlays.size() != 0) {
	                        itemizedoverlay.removeOverlay(playerOverlayItem);
	                        mapOverlays.remove(itemizedoverlay);
	                    }

	                    // Add the point to the mapview
	                    playerOverlayItem = new OverlayItem(pointPlayer, "", "player");
	                    itemizedoverlay.addOverlay(playerOverlayItem);
	                    mapOverlays.add(itemizedoverlay);
	                    

	                    mapView.postInvalidate();
	                    
	                    mapView.setSatellite(true);
	                    mapView.getController().setCenter(pointPlayer);
	                    mapView.setStreetView(false);
	                    mapView.setTraffic(false);
	                    mapView.getController().setZoom(16);
	                    mapView.displayZoomControls(true);
	                    mapView.getController().stopPanning();
	                    mapView.setBuiltInZoomControls(true);
	                    mapView.setClickable(true);

//	                    updateServerPosition();

//	                    if (host) {
//	                        if (!centerIsSet) {
//	                             if we already have a clear position
//	                             set the center position of the game
//
//	                            int temp = Connection.setCenterPosition(idgame,
//	                                    latDoubleValue.intValue(),
//	                                    lonDoubleValue.intValue());
//
//	                            point = new GeoPoint(
//	                                    latDoubleValue.intValue(),
//	                                    lonDoubleValue.intValue());
//
//	                            Log.d("CENTER LAT", latDoubleValue+"");
//	                            Log.d("CENTER LON", lonDoubleValue+"");
//
//	                            mapView.setSatellite(true);
//	                            mapView.getController().setCenter(point);
//	                            mapView.setStreetView(false);
//	                            mapView.setTraffic(false);
//	                            mapView.getController().setZoom(18);
//	                            mapView.getController().stopPanning();
//	                            mapView.setClickable(false);
//
//	                            if (temp != -1)
//	                                centerIsSet = true;
//	                            else
//	                                centerIsSet = false;
//	                        }
//	                    } else {
//
//	                        // client player
//	                        
//	                        if (!centerIsSet) {
//
//	                            // if this player is not the host
//	                            // and the center of the map
//	                            // wasn't already set
//	                            // set it and center the map
//
//	                            String centerPos = Connection.getCenterPosition(idgame);
//
//	                            if (centerPos.equalsIgnoreCase("EMPTY")) {
//	                                // ERROR
//	                                Utils.showToastShort(getBaseContext(), "CENTER POSITION ERROR");
//	                            } else {
//
//	                                String[] centerPosArray = centerPos.split("\\|");
//	                                Double centerLat = Double.parseDouble(centerPosArray[0]);
//	                                Double centerLon = Double.parseDouble(centerPosArray[1]);
//
//	                                GeoPoint centerPoint = new GeoPoint( centerLat.intValue(), centerLon.intValue() );
//
//	                                mapView.setSatellite(true);
//	                                mapView.getController().setCenter(centerPoint);
//	                                mapView.setStreetView(false);
//	                                mapView.setTraffic(false);
//
//	                                Log.d("MAX ZOOM LEVEL", mapView.getMaxZoomLevel()+"");
//
//	                                if(18 > mapView.getMaxZoomLevel() )
//	                                    mapView.getController().setZoom(mapView.getMaxZoomLevel());
//	                                else
//	                                    mapView.getController().setZoom(18);
//
//	                                mapView.getController().stopPanning();
//	                                mapView.setClickable(false);
//
//	                                centerIsSet = true;
//	                           }

//	                        }

//	                    }

	                }

	            }
			}

            public void onStatusChanged(String provider, int status,
                    Bundle extras) {
            }

            public void onProviderEnabled(String provider) {

            }

            public void onProviderDisabled(String provider) {
            }

//            public void updateServerPosition() {
//
//                Connection.setPosition(gameSessionID, latDoubleValue.intValue(), lonDoubleValue.intValue());
//            }

        };

        // Register the listener with the Location Manager to receive location
        // updates from the GPS and the cell towers
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 0, locationListener);
        //locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

    }

	
	@Override
	protected boolean isRouteDisplayed() {
		// do not visualize routing information
		return false;
	}
	
	// because of android weird location system
	// the newer location is not always the best
	// so I included some basic logic to check
	// which one is the most accurate location
	protected boolean isBetterLocation(Location location, Location currentBestLocation) {
	    if (currentBestLocation == null) {
	        // A new location is always better than no location
	        return true;
	    }

	    // Check whether the new location fix is newer or older
	    long timeDelta = location.getTime() - currentBestLocation.getTime();
	    boolean isSignificantlyNewer = timeDelta > NEWER_CHECK;
	    boolean isSignificantlyOlder = timeDelta < -NEWER_CHECK;
	    boolean isNewer = timeDelta > 0;

	    // If it's been more than NEWER_CHECK since the current location, use the new location
	    // because the user has likely moved
	    if (isSignificantlyNewer) {
	        return true;
	    // If the new location is more than NEWER_CHECK older, it must be worse
	    } else if (isSignificantlyOlder) {
	        return false;
	    }

	    // Check whether the new location fix is more or less accurate
	    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
	    boolean isLessAccurate = accuracyDelta > 0;
	    boolean isMoreAccurate = accuracyDelta < 0;
	    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

	    // Check if the old and new location are from the same provider
	    boolean isFromSameProvider = isSameProvider(location.getProvider(),
	            currentBestLocation.getProvider());

	    // Determine location quality using a combination of timeliness and accuracy
	    if (isMoreAccurate) {
	        return true;
	    } else if (isNewer && !isLessAccurate) {
	        return true;
	    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
	        return true;
	    }
	    return false;
	}
	
	public void onResume() {
        
        wl.acquire();

        switch(gamePhase) {
        // before all players join, wait players

        case Utils.CREATED:
            Log.d("LOC. GAME PHASE", "Game created");
            gamePhase = 2;
            
//            startActivity(new Intent(getBaseContext(), WaitPlayersDialog.class));
            break;
        	
        }
        
        locateMe();
        
        
        float [] results = new float[2];
	    
        for (int i = 0; i < totalPlaces; i++){
        	
        	Location.distanceBetween(
        			allPlaces[i].latE6/1E6, 
					allPlaces[i].lonE6/1E6,
					pointPlayer.getLatitudeE6()/1E6, 
					pointPlayer.getLongitudeE6()/1E6, 
					results);

        	Log.d("Dist" + i, "" + results[0]);
//        	Make a check here if it is closer than X meters and call a function
        	
        	if (results[0]<20){
        		allPlaces[i].icon.setMarker(posmarker);
        		allPlaces[i].clickable = true;
        	}
        	
        	
        	
        }
        
//        Intent anIntent=new Intent(this, Main.class);
//        PendingIntent operation=PendingIntent.getActivity(this,0,anIntent, Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); 
//        
//        
//        Log.d("testPointProx - ", ""+(double)pointTest.getLatitudeE6()/1E6);
//        Log.d("testPointProx - ", ""+(double)pointTest.getLongitudeE6()/1E6);
//        
//        
//        
//        locationManager.addProximityAlert((double)pointTest.getLatitudeE6()/1E6, (double)pointTest.getLongitudeE6()/1E6, 2, -1, operation);
//        
        super.onResume();
		
	}

	// Checks whether two providers are the same 
	private boolean isSameProvider(String provider1, String provider2) {
	    if (provider1 == null) {
	      return provider2 == null;
	    }
	    return provider1.equals(provider2);
	}

	public void onPause() {
		// Remove the listener you previously added
		locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
		locationManager.removeUpdates(locationListener);
		
//		if(refreshing) {
//		    // not in the first time
//		    stopRefreshing();
//		    wl.release(); 
//		}
			
					
		super.onPause();
	}

	@Override
	public void onClick(View v) {

    	switch(v.getId()) {
    	
//	    	case R.id.power_button_left:
//    		
//
//	    		Utils.showTopToastShort(getBaseContext(), "With the Radar you can see where\nyour team mates are on the map.\nLongpress to activate!");	
//	    		
//	    		//TO-DO load a new power right after this one is finished
//	    		
//	    		break;
//	    		
//	    	case R.id.power_button_right:
//
//	    		
//	    	    if(playerTeam == 0)
//	    	        Utils.showTopToastShort(getBaseContext(), "Jam the closest an alien and\ndon't be captured!\nLongpress to activate!");
//	    	    else
//	    	        Utils.showTopToastShort(getBaseContext(), "Unjam yourself!\nLongpress to activate!");
//	    		
//	    		
//	    		//TO-DO load a new power right after this one is finished
//	    		
//	    		break;
		
    	}

    }
	
	
    private void setupOnClickListeners() {

	}

	private void registerViews() {
//		btnPower1 = (ImageButton) this.findViewById(R.id.power_button_left);
//		btnPower2 = (ImageButton) this.findViewById(R.id.power_button_right);
	}    
    
    private void cleanOverlays() {
	    		
		// cleans the ui overlays
	    placesOverlayManager.removeOverlay(placesOverlay);
        mapOverlaysPlaces.remove(placesOverlayManager);
		mapView.postInvalidate();
    	
    }
    
    public void loadPlaces(){
    	
	    XmlPullParser parser = getResources().getXml(R.xml.places);
	    StringBuilder stringBuilder = new StringBuilder();
	    int counter = 0;
	    
        try {
            while (parser.next() != XmlPullParser.END_DOCUMENT) {
            	
                String name = parser.getName();
                int id = -1;
                String placeName = null;
                Double lat = -1.0;
                Double lon = -1.0;
                
                if((name != null) && name.equals("place")) {
                	
                    int size = parser.getAttributeCount();
                    
                    for(int i = 0; i < size; i++) {
                    	
                        String attrName = parser.getAttributeName(i);
                        String attrValue = parser.getAttributeValue(i);
                        
                        if((attrName != null) && attrName.equals("id")) {      	
                            id = new Integer(attrValue);       
                        } else if ((attrName != null) && attrName.equals("name")) {
                            placeName = attrValue;
                        } else if ((attrName != null) && attrName.equals("lat")) {	
                            lat = new Double(attrValue);    
                        } else if ((attrName != null) && attrName.equals("lon")) { 	
                            lon = new Double(attrValue); 
                        }
                    }
                    
                    if((id != -1) && (placeName != null)) {
                        Log.d("XML LOAD", id + ", " + placeName + ", " + lat + ", " + lon + "\n");
                        allPlaces[counter] = new Place(id, placeName, lat, lon, false);
                        counter++;
                        totalPlaces = counter;
                    }
                    
                   
                }
                
//                textView.setText(stringBuilder.toString());
            }
            
        }catch(Exception e) {
            Log.e("ERROR", e.getMessage());
        }
        
        for (int j = 0; j < totalPlaces; j++){
	    	
	    	allPlaces[j].icon = new OverlayItem(allPlaces[j].gpoint, allPlaces[j].name, j+"");
	    	placesOverlayManager.addOverlay(allPlaces[j].icon);
	    }
	    mapOverlaysPlaces.add(placesOverlayManager);
	    Utils.globalPlaces = allPlaces;
    }
	

	
}
